package com.dyna.core.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 密码字符验证类
 * @author admin
 */
public class WeakPassWordUtil {

    private final static String NOT_REPEAT = "4";

    /**
     * 密码连续性验证 连续字符串返回true
     * @param password 传入的校验字符串
     * @return Boolean
     */
    public static Boolean checkNuml(String password){
        boolean is = true;
        String v = isRePeat(password);
        if(NOT_REPEAT.equals(v)){
            return false;
        }else {
            return simpleLetterAndNumCheck(password,password.length());
        }
    }

    public static String SPECIAL_CHAR = "!#$%&'()*+,-./:;<=>?@[]^_`{|}~";

    /**
     * 判断字符串是否同时包含数字和字母
     * @param str  传入的校验字符串
     * @return true 正确 false 错误
     */
    public static boolean isLetterDigit(String str) {
        //定义一个boolean值，用来表示是否包含数字
        boolean isDigit = false;
        //定义一个boolean值，用来表示是否包含小写字母
        boolean isLowerCase = false;
        //定义一个boolean值，用来表示是否包含大写字母
        boolean isUpperCase = false;
        //定义一个boolean值，用来表示是否包含特殊字符
        boolean isSpecial = false;
        for (int i = 0; i < str.length(); i++) {
            //用char包装类中的判断数字的方法判断每一个字符
            if (Character.isDigit(str.charAt(i))) {
                isDigit = true;
            } else if (Character.isLowerCase(str.charAt(i))) {
                //用char包装类中的判断字母的方法判断每一个字符
                isLowerCase = true;
            } else if (Character.isUpperCase(str.charAt(i))) {
                isUpperCase = true;
            }else if(SPECIAL_CHAR.indexOf(str.charAt(i)) != -1) {
                isSpecial = true;
            }
        }
        boolean isRight = isDigit && isLowerCase && isUpperCase && isSpecial;
        return isRight;
    }

    /**
     * 密码重复性验证 重复字符串返回true
     * @param password 传入的校验字符串
     * @return boolean
     */
    public static boolean checkSame(String password){
        char [] value = password.toCharArray();
        List<String> list = new ArrayList<>();
        for (char c : value) {
            list.add( String.valueOf(c));
        }
        Map<String, Long> map = new HashMap<>(16);
        for (String s : list) {
            map.put(s,1L);
        }
        return map.size() == 1;
    }

    /**
     * 校验字符串连续多少位是纯数字或者纯字母(字母区分大小写)
     * @param value 密码
     * @param length 校验长度,默认6为
     * @return boolean
     */
    public static boolean simpleLetterAndNumCheck(String value, int length){
        //是否不合法
        boolean isValidate = false;
        //
        int i = 0;
        //计数器
        int counter = 1;
        //
        for(; i < value.length() -1;) {
            //当前ascii值
            int currentAscii = Integer.valueOf(value.charAt(i));
            //下一个ascii值
            int nextAscii = Integer.valueOf(value.charAt(i + 1));
            //满足区间进行判断
            if( (rangeInDefined(currentAscii, 48, 57) || rangeInDefined(currentAscii, 65, 90)
                    || rangeInDefined(currentAscii, 97, 122)) && (rangeInDefined(nextAscii, 48, 57)
                    || rangeInDefined(nextAscii, 65, 90) || rangeInDefined(nextAscii, 97, 122)) ) {
                //计算两数之间差一位则为连续
                if(Math.abs((nextAscii - currentAscii)) == 1){
                    //计数器++
                    counter++;
                }else{
                    //否则计数器重新计数
                    counter = 1;
                }
            }
            //满足连续数字或者字母
            if(counter >= length){
                return !isValidate;
            }
            i++;
        }
        return isValidate;
    }

    /**
     * 判断一个数字是否在某个区间
     * @param current 当前比对值
     * @param min   最小范围值
     * @param max   最大范围值
     * @return boolean
     */
    public static boolean rangeInDefined(int current, int min, int max) {
        //
        return Math.max(min, current) == Math.min(current, max);
    }


    /**
     * 判断字符重复性
     * @param str str
     * @return 1 大写重复字母 2小写重复字母 3数字重复 4非重复数据
     */
    public static String isRePeat(String str) {
        Pattern pattern1 = Pattern.compile("[a-z]*");
        Pattern pattern2 = Pattern.compile("[A-Z]*");
        Pattern pattern3 = Pattern.compile("[0-9]*");
        Matcher matcher1 = pattern1.matcher(str);
        Matcher matcher2 = pattern2.matcher(str);
        Matcher matcher3 = pattern3.matcher(str);
        if (matcher1.matches()) {
            return "1";
        } else if (matcher2.matches()) {
            return "2";
        } else if (matcher3.matches()) {
            return "3";
        } else {
            return NOT_REPEAT;
        }
    }
}